package jn.chen.utils.timer;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.time.LocalDateTime;
import java.util.Timer;
import java.util.TimerTask;

/**
 * {@link #timer}
 * {@link #timerPeriod}
 * {@link #timerFixedRate}
 * schedule 与 scheduleAtFixedRate 区别
 * schedule：每次执行完当前任务后，然后间隔一个period的时间再执行下一个任务；
 * 当某个任务执行周期大于时间间隔时，依然按照间隔时间执行下个任务,即它保证了任务之间执行的间隔。
 * scheduleAtFixedRate：每次执行时间为上一次任务开始起向后推一个period间隔，
 * 也就是说下次执行时间相对于上一次任务开始的时间点；按照上述的例子，它保证了总时间段内的任务的执行次数
 *
 * @className: ScheduledTasks
 * @author: chenLin
 * @version: 1.0.0
 * @description:
 * @date: 2022/11/9 0009 14:37
 * {Timer底层是使用一个单线来实现多个Timer任务处理的，
 * 所有任务都是由同一个线程来调度，所有任务都是串行执行，
 * 意味着同一时间只能有一个任务得到执行，而前一个任务的延迟或者异常会影响到之后的任务。}
 */
@Slf4j
public class ScheduledTasks extends Thread {

    /**
     * 延时任务
     *
     * @throws InterruptedException
     */
    public static void timer() throws InterruptedException {
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                log.info("timer-task @{}", LocalDateTime.now());
            }
        }, 1000);
        Thread.sleep(3000);
        timer.cancel();
    }

    /**
     * 周期任务
     *
     * @throws InterruptedException
     */
    @SneakyThrows
    public static void timerPeriod() {
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @SneakyThrows
            public void run() {
                log.info("timer-task @{}", LocalDateTime.now());
            }
        }, 500, 1000);
        //设置线程重复执行的累计时长
        Thread.sleep(Long.MAX_VALUE);
        timer.cancel();
    }

    /**
     * 延时0.5s执行, 每秒执行一次, 十秒后停止
     */
    @SneakyThrows
    public static void timerFixedRate() {
        Timer timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask() {
            int count = 0;

            @SneakyThrows
            public void run() {
                if (count++ == 2) {
                    // 某一次执行时间超过了period(执行周期）
                    Thread.sleep(5000);
                }
                log.info("执行时间 {}", LocalDateTime.now());

            }
        }, 500, 1000);
        Thread.sleep(10000);
        timer.cancel();
    }
}
